﻿using System;
using System.Collections.Generic;
using System.Text;
using Model;
using System.Collections;
using Components;
using System.Data;

namespace ServiceHelper
{
    /// <summary>
    /// 登录上下文
    /// </summary>
    public class Context
    {
        private static readonly string[] refCols = new string[] { "guid", "usercode", "username", "comcode", "ltime" };
        /// <summary>
        /// 键 | 值 => Guid | 用户对象
        /// </summary>
        private static Hashtable Users = null;

        //用户保存登录时客户端的硬盘序列号
        private static Hashtable _tmps = null;

        /// <summary>
        /// 存放用户的公共信息
        /// </summary>
        private static Hashtable Coms = null;
        /// <summary>
        /// 存放私钥的集合 Guid => 登录验证票
        /// </summary>
        private static Hashtable Ps = null;

        private static Hashtable Guids = null;

        private static Hashtable UpTime = null;

        /// <summary>
        /// 将当前登录用户加入上下文
        /// </summary>
        /// <param name="user"></param>
        /// <returns></returns>
        public static bool AddUser(Sys0a00 user, ContextUser cuser, bool isCut, ref String msg)
        {
            if (null == user)
            {
                msg = "用户可能已经被删除！";
                return false;
            }

            if (Guids == null)
            {
                Guids = new Hashtable();
                Users = new Hashtable();
                UpTime = new Hashtable();
                Coms = new Hashtable();
            }

            string guid = Guid.NewGuid().ToString(); //创建新的用户标识

            //isCut 是否是意外退出
            if (Guids.ContainsKey(user.Usercode)) //用户已经登录  && !isCut
            {
                //msg = string.Format("（{0}）用户已经登录, 请{1}分钟后后再试！", user.Usercode, Global.SESSION_OUT_TIME);
                //LogHelper.Entity.Out(string.Format("用户{0}重复登录，被拦截下来了！", user.Usercode));
                //return false;

                object oldGuid = Guids[user.Usercode];
                LogHelper.Entity.Out(string.Format("用户{0}重复登录，前一个登录实例被踢除！", user.Usercode));
                RemoveGuid(oldGuid.ToString());
            }

            LogHelper.Entity.Out(string.Format("用户{0}成功登录！", user.Usercode));

            Guids[user.Usercode] = guid;
            Users[guid] = user;
            UpTime[guid] = DateTime.Now; // 保存下当前登录者的时间
            Coms[guid] = cuser; // 保存下当前登录者的时间

            msg = guid;
            return true;
        }

        /// <summary>
        /// 得到Session列表
        /// </summary>
        /// <returns></returns>
        public static DataTable GetSessionList()
        {
            if (Users == null) return null;

            DataTable dt = DataTableHelper.Entity.MarkColumn(null, refCols);

            string guid;
            ContextUser sys0a00;
            foreach (DictionaryEntry entry in Users)
            {
                DataRow dr = dt.NewRow();
                guid = entry.Key.ToString();
                sys0a00 = Coms[guid] as ContextUser;

                dr["guid"] = guid;
                dr["usercode"] = null == sys0a00 ? "" : sys0a00.Uesrcode;
                dr["username"] = null == sys0a00 ? "" : sys0a00.Empname;
                dr["comcode"] = null == sys0a00 ? null : sys0a00.Comcode;
                dr["ltime"] = UpTime[guid];

                dt.Rows.Add(dr);
            }

            return dt;
        }

        /// <summary>
        /// 根据用户标识得到登录用户信息
        /// </summary>
        /// <param name="guid"></param>
        /// <returns></returns>
        public static Sys0a00 GetUser(string guid)
        {
            if (null == Users) return null;
            return Users.ContainsKey(guid) ? Users[guid] as Sys0a00 : null;
        }

        public static ContextUser GetComInfo(string guid)
        {
            if (null == Coms) return null;
            return Coms.ContainsKey(guid) ? Coms[guid] as ContextUser : null;
        }

        /// <summary>
        /// 得到数据库标识 公司.部门.用户名
        /// </summary>
        /// <param name="guid"></param>
        /// <returns></returns>
        public static ContextUser GetComInfoByUsercode(string usercode)
        {
            if (null == Guids || !Guids.ContainsKey(usercode)) return new ContextUser();

            return GetComInfo(Validation.ToString(Guids[usercode]));
        }

        /// <summary>
        /// 刷新当前登录者的最后一次操作时间
        /// </summary>
        /// <param name="guid"></param>
        /// <returns></returns>
        public static bool Refresh(string guid)
        {
            if (null == UpTime || !UpTime.ContainsKey(guid)) return false;
            UpTime[guid] = DateTime.Now;
            return true;
        }

        /// <summary>
        /// 得到数据库标识 公司.部门.用户名
        /// </summary>
        /// <param name="guid"></param>
        /// <returns></returns>
        public static string GetAppId(string guid)
        {
            ContextUser user = Context.GetComInfo(guid);

            return (null == user ? "" : user.Comcode + ".")
                + (null == user ? "" : user.Depcode + ".")
                + Context.GetUserCode(guid);
        }

        /// <summary>
        /// 为字段自动加入Where 条件
        /// </summary>
        /// <param name="fieldName"></param>
        /// <param name="guid"></param>
        /// <param name="addOp">是否自动加入And连接符</param>
        /// <returns></returns>
        public static string BuildAppWhere(string fieldName, string guid, bool addOp)
        {
            string comocde = Context.GetComInfo(guid).Comcode;
            return string.Format(" {0} {1} like '{2}.%' ", (addOp ? "AND" : ""), fieldName,
                string.IsNullOrEmpty(comocde) ? "XXXXXX" : comocde);
        }

        /// <summary>
        /// 得到公司标识
        /// </summary>
        /// <param name="guid"></param>
        /// <returns></returns>
        public static string GetComcode(string guid)
        {
            ContextUser user = Context.GetComInfo(guid);
            return (null == user) ? "XXXXXX" : user.Comcode;
        }

        /// <summary>
        /// 得到数据库标识 公司.部门.用户名
        /// </summary>
        /// <param name="guid"></param>
        /// <returns></returns>
        public static string GetAppByUserCode(string usercode)
        {
            if (null == Guids || !Guids.ContainsKey(usercode)) return "";

            return GetAppId(Validation.ToString(Guids[usercode]));
        }

        /// <summary>
        /// 得到公司标识
        /// </summary>
        /// <param name="guid"></param>
        /// <returns></returns>
        public static string GetComcodeByUsercode(string usercode)
        {
            if (null == Guids || !Guids.ContainsKey(usercode)) return "";

            return GetComcode(Validation.ToString(Guids[usercode]));
        }

        /// <summary>
        /// 得到用户编码
        /// </summary>
        /// <param name="guid"></param>
        /// <returns></returns>
        public static string GetUserCode(string guid)
        {
            Sys0a00 user = GetUser(guid);
            return null == user ? "" : user.Usercode;
        }

        /// <summary>
        /// 根据用户编码得到登录标识
        /// </summary>
        /// <param name="uesrcode"></param>
        /// <returns></returns>
        public static string GetGuid(string uesrcode)
        {
            if (null == Guids || !Guids.ContainsKey(uesrcode)) return "";

            return Validation.ToString(Guids[uesrcode]);
        }

        public static void AddMac(MacKey _tmp)
        {
            if (_tmps == null)
                _tmps = new Hashtable();

            _tmps[_tmp.Mac] = _tmp;
        }

        /// <summary>
        /// 得到登录的验证票
        /// </summary>
        /// <param name="mac"></param>
        /// <returns></returns>
        public static string GetSKey(string mac)
        {
            return (_tmps == null || !_tmps.ContainsKey(mac)) ? null : (_tmps[mac] as MacKey).Key;
        }

        public static void RemoveLoginKey(string mac)
        {
            if (_tmps == null || !_tmps.ContainsKey(mac)) return;
            _tmps.Remove(mac);
        }

        /// <summary>
        /// 添加登录验证票和私钥的关系集合
        /// </summary>
        /// <param name="guid"></param>
        /// <param name="loginGuid"></param>
        public static void AddPs(string guid, string loginGuid)
        {
            if (null == Ps)
                Ps = new Hashtable();

            Ps[guid] = loginGuid;
        }

        public static string GetLoginPs(string guid)
        {
            if (null == Ps || !Ps.ContainsKey(guid)) return "";
            return Ps[guid].ToString();
        }

        /// <summary>
        /// 根据时间回收用户标识
        /// <param name="span">约定多少分钟算过期(分钟)</param>
        /// </summary>
        public static void Callback(int span)
        {
            if (null == UpTime) return;
            TimeSpan tp = TimeSpan.MinValue;
            DateTime now = DateTime.Now;
            string usercode = "";
            string key = "";
            List<string> keys = null;
            foreach (DictionaryEntry entry in UpTime)
            {
                tp = now.Subtract(Convert.ToDateTime(entry.Value)); //计算两个
                if (tp.Minutes > span) //这还得了，都已经失效了,移除标识
                {
                    key = entry.Key.ToString();
                    usercode = ((Sys0a00)Users[key]).Usercode;
                    Guids.Remove(usercode); //移除Users
                    Users.Remove(key);
                    Coms.Remove(key);
                    Ps.Remove(key);

                    LogHelper.Entity.Out(string.Format("用户{0}的验证票被自动回收了！", usercode));

                    if (keys == null)
                    {
                        keys = new List<string>();
                    }

                    keys.Add(key);
                }
            }

            if (keys != null)
            {
                foreach (string k in keys)
                {
                    UpTime.Remove(k);
                }
            }

            keys = null;
            MacKey mac = null;
            tp = TimeSpan.MinValue;
            //检查登录验证票是否有过期的，过期则移除
            foreach (DictionaryEntry entry in _tmps)
            {
                mac = entry.Value as MacKey;
                if (mac == null) continue;

                tp = now.Subtract(Convert.ToDateTime(mac.Time)); //计算两个
                if (tp.Minutes > span) //这还得了，都已经失效了,移除标识
                {
                    if (keys == null)
                    {
                        keys = new List<string>();
                    }

                    keys.Add(entry.Key.ToString());
                }
            }

            if (keys != null)
            {
                foreach (string k in keys)
                {
                    _tmps.Remove(k);
                }
            }
        }

        /// <summary>
        /// 移除用户标识
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public static string RemoveGuid(string key)
        {
            if (!Users.ContainsKey(key)) return "";

            string usercode = ((Sys0a00)Users[key]).Usercode;
            if (Guids.ContainsKey(usercode))
                Guids.Remove(usercode); //移除Users
            if (Users.ContainsKey(key))
                Users.Remove(key);
            if (UpTime.ContainsKey(key))
                UpTime.Remove(key);
            if (Coms.ContainsKey(key))
                Coms.Remove(key);
            if (Ps.ContainsKey(key))
                Ps.Remove(key);

            LogHelper.Entity.Out(string.Format("用户{0}成功登出！", usercode));

            return "";
        }

        /// <summary>
        /// 检查用户是否已经登陆
        /// </summary>
        /// <returns></returns>
        public static bool CheckUser(string guid)
        {
            //都是想不登陆就直接访问数据的，统统拒绝
            if (string.IsNullOrEmpty(guid)) return false;
            if (!Users.ContainsKey(guid)) return false;

            //刷新最后一次操作时间
            return Refresh(guid);
        }

        public static string Decrypt(string guid, string value)
        {
            string key = GetLoginPs(guid);
            return SecurityEncryption.Decrypt(value, key);
        }
    }
}

